#include <ximera/physics/ode/joint.hpp>

namespace ximera { namespace physics { namespace ode
{
    BallJoint::BallJoint()
    {
    }

    math::Vector3 BallJoint::anchor0() const
    {
        math::Vector3 result;
        dJointGetBallAnchor(_jointID, result.array());
        return result;
    }

    math::Vector3 BallJoint::anchor1() const
    {
        math::Vector3 result;
        dJointGetBallAnchor2(_jointID, result.array());
        return result;
    }

    void BallJoint::anchor(math::Vector3 const& value)
    {
        dJointSetBallAnchor(_jointID, value.x, value.y, value.z);
    }

    void BallJoint::attachSpace(Space* space)
    {
        joint_base::attachSpace(space);

        if (!_jointID)
            dJointCreateBall(_worldID, 0);
    }

    // --------------------------------------------

    HingeJoint::HingeJoint()
    {
    }

    math::Vector3 HingeJoint::anchor0() const
    {
        math::Vector3 result;
        dJointGetHingeAnchor(_jointID, result.array());
        return result;
    }

    math::Vector3 HingeJoint::anchor1() const
    {
        math::Vector3 result;
        dJointGetHingeAnchor2(_jointID, result.array());
        return result;
    }

    void HingeJoint::anchor(math::Vector3 const& value)
    {
        dJointSetHingeAnchor(_jointID, value.x, value.y, value.z);
    }

    math::Vector3 HingeJoint::axis() const
    {
        math::Vector3 result;
        dJointGetHingeAxis(_jointID, result.array());
        return result;
    }

    void HingeJoint::axis(math::Vector3 const& value)
    {
        dJointSetHingeAxis(_jointID, value.x, value.y, value.z);
    }

    Real HingeJoint::angle() const
    {
        return dJointGetHingeAngle(_jointID);
    }

    void HingeJoint::attachSpace(Space* space)
    {
        joint_base::attachSpace(space);

        if (!_jointID)
            dJointCreateHinge(_worldID, 0);
    }

    // --------------------------------------------

    SliderJoint::SliderJoint()
    {
    }

    math::Vector3 SliderJoint::axis() const
    {
        math::Vector3 result;
        dJointGetSliderAxis(_jointID, result.array());
        return result;
    }

    void SliderJoint::axis(math::Vector3 const& value)
    {
        dJointSetSliderAxis(_jointID, value.x, value.y, value.z);
    }

    math::Vector3 SliderJoint::position() const
    {
        return math::Vector3(dJointGetSliderPosition(_jointID));
    }

    void SliderJoint::attachSpace(Space* space)
    {
        joint_base::attachSpace(space);

        if (!_jointID)
            dJointCreateSlider(_worldID, 0);
    }

    // --------------------------------------------

    UniversalJoint::UniversalJoint()
    {
    }

    math::Vector3 UniversalJoint::anchor0() const
    {
        math::Vector3 result;
        dJointGetUniversalAnchor(_jointID, result.array());
        return result;
    }

    math::Vector3 UniversalJoint::anchor1() const
    {
        math::Vector3 result;
        dJointGetUniversalAnchor2(_jointID, result.array());
        return result;
    }

    void UniversalJoint::anchor(math::Vector3 const& value)
    {
        dJointSetUniversalAnchor(_jointID, value.x, value.y, value.z);
    }

    math::Vector3 UniversalJoint::axis0() const
    {
        math::Vector3 result;
        dJointGetUniversalAxis1(_jointID, result.array());
        return result;
    }

    void UniversalJoint::axis0(math::Vector3 const& value)
    {
        dJointSetUniversalAxis1(_jointID, value.x, value.y, value.z);
    }

    math::Vector3 UniversalJoint::axis1() const
    {
        math::Vector3 result;
        dJointGetUniversalAxis2(_jointID, result.array());
        return result;
    }

    void UniversalJoint::axis1(math::Vector3 const& value)
    {
        dJointSetUniversalAxis2(_jointID, value.x, value.y, value.z);
    }

    void UniversalJoint::attachSpace(Space* space)
    {
        joint_base::attachSpace(space);

        if (!_jointID)
            dJointCreateUniversal(_worldID, 0);
    }

    // --------------------------------------------

    Hinge2Joint::Hinge2Joint()
    {
    }

    math::Vector3 Hinge2Joint::anchor0() const
    {
        math::Vector3 result;
        dJointGetHinge2Anchor(_jointID, result.array());
        return result;
    }

    math::Vector3 Hinge2Joint::anchor1() const
    {
        math::Vector3 result;
        dJointGetHinge2Anchor2(_jointID, result.array());
        return result;
    }

    void Hinge2Joint::anchor(math::Vector3 const& value)
    {
        dJointSetHinge2Anchor(_jointID, value.x, value.y, value.z);
    }

    math::Vector3 Hinge2Joint::axis0() const
    {
        math::Vector3 result;
        dJointGetHinge2Axis1(_jointID, result.array());
        return result;
    }
    void Hinge2Joint::axis0(math::Vector3 const& value)
    {
        dJointSetHinge2Axis1(_jointID, value.x, value.y, value.z);
    }

    math::Vector3 Hinge2Joint::axis1() const
    {
        math::Vector3 result;
        dJointGetHinge2Axis2(_jointID, result.array());
        return result;
    }

    void Hinge2Joint::axis1(math::Vector3 const& value)
    {
        dJointSetHinge2Axis2(_jointID, value.x, value.y, value.z);
    }

    void Hinge2Joint::attachSpace(Space* space)
    {
        joint_base::attachSpace(space);

        if (!_jointID)
            dJointCreateHinge2(_worldID, 0);
    }
}}}
